/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.cef.designtime.api.collection.GspEnumValueCollection;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.ElementDefaultVauleType;
import com.inspur.edp.cef.designtime.api.element.EnumIndexType;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.element.GspEnumValue;
import com.inspur.edp.cef.designtime.api.entity.GspCommonField;
import com.inspur.edp.cef.designtime.api.entity.MappingInfo;
import com.inspur.edp.cef.designtime.api.entity.MappingRelation;
import com.inspur.edp.cef.designtime.api.util.Guid;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.GspCommonElement;
import com.inspur.edp.das.commonmodel.entity.object.GspColumnGenerate;
import com.inspur.edp.das.commonmodel.util.HandleAssemblyNameUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MdpkgService;
import com.inspur.edp.lcm.metadata.spi.MetadataContentManager;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import io.netty.util.internal.StringUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 业务实体元数据上下文
 *
 * @author haoxiaofei
 */
public class BEMetadataContentManager implements MetadataContentManager {

    private Boolean enableEntryBills = false;

    /**
     * 构造业务实体元数据
     *
     * @param metadata 元数据
     */
    public final void build(GspMetadata metadata) {
        String metadataID = metadata.getHeader().getId();
        String metadataName = metadata.getHeader().getName();
        String metadataCode = metadata.getHeader().getCode();
        String metadataAssembly = metadata.getHeader().getNameSpace();
        String relativePath = metadata.getRelativePath();

        Arrays.asList(metadata.getExtendProperty()).get(0);
        Map extendPropertyMap = null;

        if (!StringUtil.isNullOrEmpty(metadata.getExtendProperty())) {
            try {
                extendPropertyMap = new ObjectMapper().readValue(metadata.getExtendProperty(), Map.class);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("获取ExtendProperty失败" + e.toString());
            }
        }

        if (extendPropertyMap != null) {
            enableEntryBills = (Boolean) extendPropertyMap.get("enableEntryBills");
        }

        GspBusinessEntity be = InitBizEntity(metadataID, metadataName, metadataCode, metadataAssembly,
            relativePath);
        metadata.setContent(be);
    }

    private GspBusinessEntity InitBizEntity(String metadataID, String metadataName,
        String metadataCode, String metadataAssembly, String relativePath) {
        GspBusinessEntity be = new GspBusinessEntity();
        be.setID(metadataID);
        be.setCode(metadataCode);
        be.setName(metadataName);
        be.setComponentAssemblyName(metadataAssembly);
        be.setDotnetGeneratingAssembly(metadataAssembly);
        be.setGeneratingAssembly(HandleAssemblyNameUtil.convertToJavaPackageName(metadataAssembly));
        be.setIsUseNamespaceConfig(true);
        // 新建be默认为精简生成
        be.setSimplifyGen(true);
        GspBizEntityObject mainObject = InitMainObject(metadataName, metadataCode, be, relativePath);
        be.setMainObject(mainObject);
        return be;
    }

    private GspBizEntityObject InitMainObject(String objName, String objCode, GspBusinessEntity be,
        String relativePath) {
        GspBizEntityObject mainObj = new GspBizEntityObject();
        mainObj.setID(UUID.randomUUID().toString());
        mainObj.setCode(objCode);
        mainObj.setName(objName);

        // ID字段
        GspBizEntityElement idElement = GetIDElement();
        mainObj.setColumnGenerateID(new GspColumnGenerate());
        mainObj.getColumnGenerateID().setElementID(idElement.getID());
        mainObj.getColumnGenerateID().setGenerateType("Guid");
        mainObj.getContainElements().add(idElement);

        // 版本控制字段
        GspBizEntityElement versionControlElement = GetVersionControlElement();
        mainObj.getContainElements().add(versionControlElement);
        be.getVersionContronInfo().setVersionControlElementId(versionControlElement.getID());

        if (enableEntryBills) {
            addMetadataPackageRefs(relativePath);
            GspBizEntityElement billStatusUdtElement = getBillStatusUdtElement(mainObj);
            mainObj.getContainElements().add(billStatusUdtElement);
            GspBizEntityElement bizEntityElement = getBillEntityUdtElement(mainObj);
            mainObj.getContainElements().add(bizEntityElement);
        }

        // 逻辑删除

        mainObj.getLogicDeleteControlInfo().setEnableLogicDelete(false);
        mainObj.getLogicDeleteControlInfo().setLogicDeleteControlElementId("");

        mainObj.initMainObject();
        return mainObj;
    }

    private GspBizEntityElement GetIDElement() {
        GspBizEntityElement idElement = new GspBizEntityElement();
        idElement.setID(UUID.randomUUID().toString());
        idElement.setCode("ID");
        idElement.setName("主键");
        idElement.setLabelID("ID");
        idElement.setMDataType(GspElementDataType.String);
        idElement.setObjectType(GspElementObjectType.None);
        idElement.setLength(36);
        idElement.setPrecision(0);
        idElement.setIsRequire(true);
        return idElement;
    }

    private GspBizEntityElement GetVersionControlElement() {

        GspBizEntityElement idElement = new GspBizEntityElement();
        idElement.setID(UUID.randomUUID().toString());
        idElement.setCode("Version");
        idElement.setName("版本");
        idElement.setLabelID("Version");
        idElement.setMDataType(GspElementDataType.DateTime);
        idElement.setObjectType(GspElementObjectType.None);
        idElement.setLength(0);
        idElement.setPrecision(0);
        idElement.setIsRequire(false);
        return idElement;
    }

    private GspBizEntityElement getBillStatusUdtElement(GspBizEntityObject obj) {
        GspBizEntityElement billStatusElement = new GspBizEntityElement();
        billStatusElement.setID(UUID.randomUUID().toString());
        billStatusElement.setCode("BillStatus");
        billStatusElement.setName("状态");
        billStatusElement.setLabelID("BillStatus");
        billStatusElement.setObjectType(GspElementObjectType.Enum);
        billStatusElement.setMDataType(GspElementDataType.String);
        billStatusElement.setIsUdt(true);
        billStatusElement.setIsRequire(false);
        billStatusElement.setLength(36);
        billStatusElement.setPrecision(0);
        billStatusElement.setUdtID("a0b19650-0101-468f-ae3f-40c76c0f06b0");
        billStatusElement.setUdtName("状态");
        billStatusElement.setEnumIndexType(EnumIndexType.Integer);
        billStatusElement.setContainEnumValues(getBillStatusEnumValues());
        billStatusElement.setChildElements(getBillStatusUdtChildElements(obj));
        billStatusElement.setMappingRelation(
            getMappingRelation(billStatusElement.getChildElements().get(0).getID(),
                billStatusElement.getUdtID()));
        return billStatusElement;
    }

    private GspElementCollection getBillStatusUdtChildElements(GspBizEntityObject obj) {
        GspElementCollection collection = new GspElementCollection(obj);
        GspBizEntityElement field = new GspBizEntityElement();
        field.setID(UUID.randomUUID().toString());
        field.setName("状态");
        field.setLabelID("BillStatus_BillStatus");
        field.setCode("BillStatus_BillStatus");
        field.setIsRef(false);
        field.setObjectType(GspElementObjectType.None);
        field.setMDataType(GspElementDataType.String);
        field.setDefaultValueType(ElementDefaultVauleType.Vaule);
        field.setLength(36);
        field.setPrecision(0);
//        field.setMappingRelation(getMappingRelation(field.getID(), ele.getID()));
        collection.add(field);
        return collection;
    }

    private GspEnumValueCollection getBillStatusEnumValues() {
        GspEnumValueCollection collection = new GspEnumValueCollection();
        GspEnumValue billing = new GspEnumValue();
        billing.setName("制单");
        billing.setIndex(0);
        billing.setValue("Billing");
        billing.setI18nResourceInfoPrefix("Inspur.Gsp.Common.CommonUdt.BillState.BillState.Billing");
        billing.setIsDefaultEnum(true);
        collection.addEnumValue(billing);

        GspEnumValue submitApproval = new GspEnumValue();
        submitApproval.setName("提交审批");
        submitApproval.setIndex(1);
        submitApproval.setValue("SubmitApproval");
        submitApproval.setI18nResourceInfoPrefix(
            "Inspur.Gsp.Common.CommonUdt.BillState.BillState.SubmitApproval");
        submitApproval.setIsDefaultEnum(false);
        collection.addEnumValue(submitApproval);

        GspEnumValue approved = new GspEnumValue();
        approved.setName("审批通过");
        approved.setIndex(2);
        approved.setValue("Approved");
        approved.setI18nResourceInfoPrefix("Inspur.Gsp.Common.CommonUdt.BillState.BillState.Approved");
        approved.setIsDefaultEnum(false);
        collection.addEnumValue(approved);

        GspEnumValue approvalNotPassed = new GspEnumValue();
        approvalNotPassed.setName("审批不通过");
        approvalNotPassed.setIndex(3);
        approvalNotPassed.setValue("ApprovalNotPassed");
        approvalNotPassed.setI18nResourceInfoPrefix(
            "Inspur.Gsp.Common.CommonUdt.BillState.BillState.ApprovalNotPassed");
        approvalNotPassed.setIsDefaultEnum(false);
        collection.addEnumValue(approvalNotPassed);

        return collection;
    }

    private GspBizEntityElement getBillEntityUdtElement(GspBizEntityObject obj) {
        GspBizEntityElement billEntityElement = new GspBizEntityElement();
        billEntityElement.setID(UUID.randomUUID().toString());
        billEntityElement.setCode("ProcessInstance");
        billEntityElement.setLabelID("ProcessInstance");
        billEntityElement.setName("流程实例");
        billEntityElement.setObjectType(GspElementObjectType.None);
        billEntityElement.setMDataType(GspElementDataType.String);
        billEntityElement.setLength(36);
        billEntityElement.setPrecision(0);
        billEntityElement.setIsUdt(true);
        billEntityElement.setIsRequire(false);
        billEntityElement.setUdtID("2e1beb7d-ad8f-4da3-a430-c8a7f2162135");
        billEntityElement.setUdtName("流程实例");
        billEntityElement.setEnumIndexType(EnumIndexType.Integer);
        billEntityElement.setChildElements(getBillEntityUdtChildElement(obj));
        billEntityElement.setMappingRelation(
            getMappingRelation(billEntityElement.getChildElements().get(0).getID(),
                billEntityElement.getUdtID()));
        return billEntityElement;
    }

    private GspElementCollection getBillEntityUdtChildElement(GspBizEntityObject obj) {
        GspElementCollection collection = new GspElementCollection(obj);
        GspBizEntityElement field = new GspBizEntityElement();
        field.setID(UUID.randomUUID().toString());
        field.setLabelID("ProcessInstance_ProcessInstance");
        field.setCode("ProcessInstance_ProcessInstance");
        field.setIsRef(false);
        field.setObjectType(GspElementObjectType.None);
        field.setMDataType(GspElementDataType.String);
        field.setDefaultValueType(ElementDefaultVauleType.Vaule);
        field.setLength(36);
        field.setPrecision(0);
        collection.add(field);
        return collection;
    }

    private MappingRelation getMappingRelation(String keyInfo, String valueInfo) {
        MappingRelation mappingRelation = new MappingRelation();
        MappingInfo info = new MappingInfo();
        info.setKeyInfo(keyInfo);
        info.setValueInfo(valueInfo);
        mappingRelation.add(info);
        return mappingRelation;
    }

    private void addMetadataPackageRefs(String path) {
        if (path == null || "".equals(path)) {
            throw new RuntimeException("获取工程相对路径为空");
        }
        if (path.endsWith("/be")) {
            path = path.substring(0, path.length() - 3);
        }
        MdpkgService service = SpringBeanUtils.getBean(MdpkgService.class);
        ArrayList<String> packageNames = new ArrayList<>();
        packageNames.add("Inspur.Gsp.Common.CommonUdt.mdpkg");
        service.addDepedencyAndRestore(path, packageNames);
    }
}
